#include<cstdio>//uncle-lu
#include<cstring>
#include<algorithm>
template<class T>void read(T &x)
{
    x=0;bool f=false;char ch=getchar();
    while(ch<'0'||ch>'9') { f|=(ch=='-'); ch=getchar(); }
    while(ch<='9'&&ch>='0') { x = (x<<1) + (x<<3) + (ch^48); ch=getchar(); }
    x = f ? -x : x;
    return ;
}
 
const int Mod = 998244353;
 
void add_edge(int, int);
void DFS(int, int);
void add_ans(int);
 
struct node{
    int v,next;
};
node edge[1000010];
int head[300010], cnt, tot;
int d[300010];
int n, m, ans = 1;
bool visit[300010];
 
void add_edge(int x, int y)
{
    edge[++cnt].v = y;
    edge[cnt].next=head[x];
    head[x] = cnt;
    return ;
}
 
void add_ans(int x)
{
    if(!x)return ;
    if(!ans)ans=1;
    int temp=1;
    for(int i=1;i<=x;++i)
    {
        temp<<=1;
        temp %= Mod;
    }
    temp -= 1;
    ans = (ans*temp) % Mod;
    return ;
}
 
void DFS(int x, int fa)
{
    d[x] = d[fa] + 1;
    visit[x] = true;
    for(int i = head[x];~i;i=edge[i].next)
    {
        if(edge[i].v == fa)continue;
        if(visit[edge[i].v])
        {
            if(d[edge[i].v]<d[x])
			{
				add_ans(d[x] - d[edge[i].v] + 1);
				tot += (d[x] - d[edge[i].v] + 1);
			}
            continue;
        }
        DFS(edge[i].v, x);
    }
    return ;
}
 
int main()
{
    //freopen("in","r",stdin);
    memset(head,-1,sizeof(head));
    int a, b;
    read(n);read(m);
    for(int i=1;i<=m;++i)
    {
        read(a);read(b);
        add_edge(a, b);add_edge(b, a);
    }
 
    for(int i=1;i<=n;++i)
    {
        if(!visit[i])
        {
            d[i] = 0;
            DFS(i, 0);
        }
    }

	tot = m - tot;
    int temp = 1;
    for(int i=1;i<=tot;++i)
    {
        temp<<=1;
        temp %= Mod;
    }
    ans = (ans*temp) % Mod;
 
    printf("%d",ans);
    return 0;
}
